/*
 * SHTC3驱动函数库
 * BETA1.0 为Arduino适配I2C协议的SHTC3驱动
 * 目前无CRC-8校验
 * 2022-01-11 FIRFIT AKARIN

 * 增加CRC8校验功能
 * 状态位位于finalDATA->CRCSTATUS1以及CRCSTATUS2中
 * 2022-01-27 FIRFIT AKARIN 
*/

#ifndef SHTC3_BETA0_1_HPP
#define SHTC3_BETA0_1_HPP

#include <Arduino.h>
#include <Wire.h>

#define DEV_ADDRESS 0X70

#define DEV_WAKEUPCMD_HSB 0X35
#define DEV_WAKEUPCMD_LSB 0X17

#define DEV_SLEEPCMD_HSB 0XB0
#define DEV_SLEEPCMD_LSB 0X98

/*↑唤醒及睡眠指令*/

#define DEV_CSE_READTEMP_FIRST_HSB 0X7C//当时钟延展功能开启时，若想要让温度数据先读取，使用该条指令
#define DEV_CSE_READTEMP_FIRST_LSB 0XA2

#define DEV_CSE_READRH_FIRST_HSB 0X5C//当时钟延展功能开启时，若想要湿度数据先读取，使用该条指令
#define DEV_CSE_READRH_FIRST_LSB 0X24

#define DEV_CSDE_READRH_FIRST_HSB 0X78//当时钟延展功能关闭时，若想要湿度数据先读取，使用该条指令
#define DEV_CSDE_READRH_FIRST_LSB 0X66

#define DEV_CSDE_READRH_FIRST_HSB 0X58//当时钟延展功能关闭时，若想要湿度数据先读取，使用该条指令
#define DEV_CSDE_READRH_FIRST_LSB 0XE0

typedef struct TEMPDATA{
  byte HUMIHSB;
  byte HUMILSB;
  byte HUMICRC;
  byte TEMPHSB;
  byte TEMPLSB;
  byte TEMPCRC;
};

typedef struct FinalDATA{
  double HUMI;
  double TEMP;
  bool CRCSTATUS1;
  bool CRCSTATUS2;
  };

void WakeupDEFICE()//唤醒设备
{
  Wire.begin();
  Wire.beginTransmission(DEV_ADDRESS);
  Wire.write(DEV_WAKEUPCMD_HSB);
  Wire.write(DEV_WAKEUPCMD_LSB);
  Wire.endTransmission();
  delay(25);
}

TEMPDATA ReadDATACMD()
{
  TEMPDATA READ;
  byte TEMPLA[6];//暂存数据
  Wire.begin();
  Wire.beginTransmission(DEV_ADDRESS);
  Wire.write(DEV_CSE_READRH_FIRST_HSB);
  Wire.write(DEV_CSE_READRH_FIRST_LSB);
  Wire.endTransmission();
  delay(25);

  Wire.requestFrom(DEV_ADDRESS,6);
  for(int i=0;i<6;i++)
  TEMPLA[i]=Wire.read();
  
  READ.HUMIHSB=TEMPLA[0];
  READ.HUMILSB=TEMPLA[1];
  READ.HUMICRC=TEMPLA[2];
  READ.TEMPHSB=TEMPLA[3];
  READ.TEMPLSB=TEMPLA[4];
  READ.TEMPCRC=TEMPLA[5];

  Wire.endTransmission();
  return READ;
}

int CreateCRC8(int DATA,int polynor,int init)//data:原始数据(16位),polynor:异或值,init初始值
{
    DATA ^= init;
    polynor |= 0x100;//例如原来需要被异或的值是0x31。经过这一步就会变成0x131，CRC8算法规定最高位必须为1
    polynor <<= 7;
    int result = 0;
    int cursor = 9;//目前的异或最低位位置
    int MAXDIG = 16 + 9;
    while (1)
    {
        if (((DATA & 0X8000) == 0X8000))//如果最高位为1并且没有于DATA的最后9位异或
        {
            DATA ^= polynor;
        }
        else
        {
            cursor++;
            DATA <<= 1;
        }
        if(cursor==MAXDIG)
        break;
    }
    return (DATA>>8);
}

FinalDATA GetFinalDATA(TEMPDATA FROM)
{
  FinalDATA LASTRESULT;//存放最终计算结果
  int COMBINETEMP;//将两个BYTE类型的数据整合进一个16位的int中
  unsigned int COMBINEHUMI;

  COMBINETEMP|=(FROM.TEMPHSB<<8);
  COMBINETEMP|=FROM.TEMPLSB;

  COMBINEHUMI|=(FROM.HUMIHSB<<8);
  COMBINEHUMI|=FROM.HUMILSB;

  if(CreateCRC8(COMBINEHUMI,0X31,0XFF00)==FROM.HUMICRC)//如果CRC8验证成功
  LASTRESULT.CRCSTATUS1=1;
  else
  LASTRESULT.CRCSTATUS1=0;

  if(CreateCRC8(COMBINETEMP,0X31,0XFF00)==FROM.TEMPCRC)//如果CRC8验证成功
  LASTRESULT.CRCSTATUS2=1;
  else
  LASTRESULT.CRCSTATUS2=0;

  LASTRESULT.HUMI=((double)COMBINEHUMI/65536.0)*100.0;
  LASTRESULT.TEMP=(((double)COMBINETEMP/65536.0)*175.0)-45.0;
  return LASTRESULT;
}

#endif
